Unit
	WebComponents;

Interface

Uses
	Classes,
	SysUtils,
	PWInit,
	PWMain,
	RTTIObject,
	GenericTemplate;

Type
	TActiveComponent = Class(TRTTIObject)
	Public
		Procedure Submit; Override;
	End;

	TInvisibleChilds = Class(TRTTIObject)
	Public
		Function Show: String; Override;
	End;

	TVisualComponent = Class(TActiveComponent)
	Private
		fTemplate : TTemplate;
		fVisible : Boolean;
	Public
		Function Show: String; Override;
		Procedure OnToggle(Var Msg); Message 'toggle';
	Published
		Property Visible : Boolean Read fVisible Write fVisible;
		Property Template : TTemplate Read fTemplate Write fTemplate;
	End;
	
	TCollapsibleComponent = Class(TVisualComponent)
	Private
		fCollapsed : Boolean;
	Public
		Function ShowChilds: String; Override;
		Procedure OnToggleCollapsed(Var Msg); Message 'collapse';
	Published
		Property Collapsed : Boolean Read fCollapsed Write fCollapsed;
	End;
	
	TDualTemplate = Class(TCollapsibleComponent)
	Private
		fWich : Boolean;
		fPrimary,
		fSecondary : String;
	Public
		Function Show: String; Override;
		Procedure OnToggleTemplate(Var Msg); Message 'change';
		Procedure OnToggleTemplateOn(Var Msg); Message 'secondary';
		Procedure OnToggleTemplateOff(Var Msg); Message 'primary';
	Published
		Property Wich : Boolean Read fWich Write fWich;
		Property PrimaryTemplate : String Read fPrimary Write fPrimary;
		Property SecondaryTemplate : String Read fSecondary Write fSecondary;
	End;
	
	TEditableComponent = Class(TDualTemplate)
	Private
		fEditables : TArrayOfString;
	Public
		Procedure AfterSubmit; Virtual;
		Procedure AddEditable(Const aName : String);
		Procedure OnSubmit(Var Msg); Message 'submit';
		Property Editables: TArrayOfString Read fEditables Write fEditables;
	End;

	TContainableComponent = class(TEditableComponent)
	Public
		Procedure AfterDelete; Virtual;
		Procedure AfterSubmit; Override;
		Procedure OnDelete(Var Msg); Message 'delete';
	End;
	
	TContainerComponent = Class(TCollapsibleComponent)
	Private
		fChildPrototype : TContainableComponent;
	Public
		Procedure AfterAppend(Const aObject : TContainableComponent); Virtual;
		Function DoAppend: TContainableComponent;
		Procedure DoDelete(Const aObject : TContainableComponent); Virtual;
		Procedure SaveChanges(Const aObject : TContainableComponent); Virtual;
		Procedure OnAppend(Var Msg); Message 'append';
	Published
		Property ChildPrototype : TContainableComponent Read fChildPrototype Write fChildPrototype;
	End;
	
Implementation

Procedure TActiveComponent.Submit;
Begin
	If GetCGIVar('component') = InstanceName Then
		DispatchEvent(GetCGIVar('action'))
	Else
		Inherited Submit;
End;

Function TInvisibleChilds.Show: String;
Begin
	Result := '';
End;

Function TVisualComponent.Show: String;
Begin
	fTemplate.AddRTTIChildsKey('childs').SetKeyValue(Self.InstanceName);
	fTemplate.AddRTTIObjectProperties(Self.InstanceName);
	If fVisible Then
		Result := fTemplate.Show
	Else
		Result := '';
	Result := StringReplace(Result, '<%instancename%>', InstanceName, [ rfReplaceAll, rfIgnoreCase ]);
	Result := StringReplace(Result, '<%childcount%>', IntToStr(ChildCount), [ rfReplaceAll, rfIgnoreCase ]);
End;

Procedure TVisualComponent.OnToggle(Var Msg);
Begin
	fVisible := Not(fVisible);
End;

Function TCollapsibleComponent.ShowChilds: String;
Begin
	If Not(fCollapsed) Then
		Result := Inherited ShowChilds
	Else
		Result := '';
End;

Procedure TCollapsibleComponent.OnToggleCollapsed(Var Msg);
Begin
	fCollapsed := Not(fCollapsed);
End;

Function TDualTemplate.Show: String;
Begin
	If Not(fWich) Then
		Template.FileName := fPrimary
	Else
		Template.FileName := fSecondary;
	Result := Inherited Show;
End;

Procedure TDualTemplate.OnToggleTemplate(Var Msg);
Begin
	fWich := Not(fWich);
End;

Procedure TDualTemplate.OnToggleTemplateOn(Var Msg);
Begin
	fWich := True;
	// Debug  Out(InstanceName + ' on ');
End;

Procedure TDualTemplate.OnToggleTemplateOff(Var Msg);
Begin
	fWich := False;
	// Debug  Out(InstanceName + ' off ');
End;

Procedure TEditableComponent.AfterSubmit;
Begin
	// Null...
End;

Procedure TEditableComponent.AddEditable(Const aName : String);
Begin
	SetLength(fEditables, Length(fEditables) + 1);
	fEditables[High(fEditables)] := aName;
End;

Procedure TEditableComponent.OnSubmit(Var Msg);
Var
	lCtrl : Integer;
Begin
	For lCtrl := Low(fEditables) To High(fEditables) Do
		Properties[fEditables[lCtrl]] := GetCGIVar(LowerCase(fEditables[lCtrl]));
	DispatchEvent('primary');
	AfterSubmit;
End;

Procedure TContainableComponent.AfterDelete;
Begin
	// Null...
End;

Procedure TContainableComponent.AfterSubmit;
Begin
	Inherited AfterSubmit;
	If Assigned(Owner) Then
		(Owner As TContainerComponent).SaveChanges(Self);
End;

Procedure TContainableComponent.OnDelete(Var Msg);
Begin
	If Assigned(Owner) Then
		If Owner Is TContainerComponent Then
		Begin
			(Owner as TContainerComponent).DoDelete(Self);
			AfterDelete;
		End;
End;

Procedure TContainerComponent.AfterAppend(Const aObject : TContainableComponent);
Begin
	// Null...
End;

Function TContainerComponent.DoAppend: TContainableComponent;
Begin
	Result := Factory.Clone(fChildPrototype.InstanceName) As TContainableComponent;
	Append(Result);
	// Debug WriteLn('Created object : ', Result.InstanceName);
End;

Procedure TContainerComponent.DoDelete(Const aObject : TContainableComponent);
Begin
	Delete(aObject);
End;

Procedure TContainerComponent.SaveChanges(Const aObject : TContainableComponent);
Begin
End;

Procedure TContainerComponent.OnAppend(Var Msg);
Begin
	AfterAppend(DoAppend);
End;

Initialization

	Factory.Register(TActiveComponent);
	Factory.Register(TInvisibleChilds);
	Factory.Register(TVisualComponent);
	Factory.Register(TCollapsibleComponent);
	Factory.Register(TDualTemplate);
	Factory.Register(TEditableComponent);
	Factory.Register(TContainableComponent);
	Factory.Register(TContainerComponent);

End.